local dfskey_show=require'zdc.fieldutil'.dfskey_show

module(..., package.seeall)

local function _mergeflag(pf,sf)
	if pf=='' or pf==sf or sf=='-' then return sf end
	if pf=='-' then return pf end
	if pf=='+' then if sf=='*' then return sf end return pf end
	if pf=='^' then return pf end
	assert(nil,'_mergeflag fail')
end
function GetFieldDefineShow(n,key)
	local fd,sk=n._fds[key],key
	if not fd then
		fd,sk=dfskey_show(n._dfs,key)
	end
	return fd,sk
end
local function _show_field(sflag,tab,i,name,v,_put,n)
	local _fd,name=GetFieldDefineShow(n,name)
	local val
	if not _fd then
		val=v
	else
		local ft=_fd[2]
		if ft and ft._showS then val=ft:_showS(v) else val=v end
	end
	
	local t = type(val)
	_put(sflag,string.rep(' ',2-#sflag),i)
	if t == 'nil' then
		_put(name,': ',t,'\n')
	elseif t == 'number' then
		_put(name,': ',val,'\n')
	elseif t == 'string' then
		_put(name,': ',val,'\n')
	elseif t == 'boolean' then
		_put(name,': ',tostring(val),'\n')
	elseif t == 'table' then
		_put(name,': ',zdc.doc.tostring(val),'\n')
	else
		_put(name,': ',tostring(val),'\n')
	end
end

--sflag:
--tab: tab space
--i: pre indent
--name: val's name
--val: node object
--_put: output function
--inh: true for proto val
--deep: level for subnodes
function ShowNodeEx(name,val,sflag,tab,i,_put,inh,deep)
	local t = type(val)
	_put(sflag,string.rep(' ',2-#sflag),i)
	if t == 'nil' then
		_put(name,': ',t,'\n')
	elseif t == 'number' then
		_put(name,': ',val,'\n')
	elseif t == 'string' then
		_put(name,': ',val,'\n')
	elseif t == 'boolean' then
		_put(name,': ',tostring(val),'\n')
	elseif t == 'table' then
		_put(name,'(ik=',tostring(val.__ik),',ts=',tostring(val.__ts),') {\n')
		local fs = val:__get_ordered_fields_name_lvl(1)
		for _,v in ipairs(fs) do
			local flag,temp = val:__get_flag_val(v)
			if temp == nil then temp='' end
			if temp ~= nil and (flag ~= '@' or inh) then
				flag=_mergeflag(sflag,flag)
				_show_field(flag,tab,i..tab,v,temp,_put,val)
			end
		end
		local otherfun=val.__get_other_fields_withdel
		local getflagvalsub=val.__get_flag_val_withdel or val.__get_flag_val
		if otherfun then
			fs=otherfun(val,nil,true)
		else
			fs = val:__get_other_fields()
		end
		for _,v in ipairs(fs) do
			local flag,temp = getflagvalsub(val,v)
			if temp == nil then temp='' end
			if temp~=nil and (flag ~= '@' or inh) then
				flag=_mergeflag(sflag,flag)
				if type(temp)=='table' then
					if deep and deep > 0 then
						ShowNodeEx(v,temp,flag,tab,i..tab,_put,inh,deep-1)
					end
				else
					_show_field(flag,tab,i..tab,v,temp,_put,val)
				end
			end
		end
		if not otherfun then
			if deep and deep > 0 then
				fs = val:__get_child_all()
				--fs = val:__get_child_ex('','id-,ik-',3)
				local sikt=zdc.idutil.SortChildNodes(fs)
				for _,sid in pairs(sikt) do
					ShowNodeEx(sid,fs[sid],'',tab,i..tab,_put,inh,deep-1)
				end
			end
		end
		_put(sflag,string.rep(' ',2-#sflag),i,'}\n')
	else
		assert(nil,'bad type:' .. t)
	end
end

function ShowNode(node,_put,inh,deep)
    if deep and type(deep)~='number' then deep=10000 end
	return ShowNodeEx(node.__id,node,'','  ','',_put,inh,deep)
end
